﻿using System;
using System.Net.Sockets;
using eLibrary.Environment;
using Letter.Net.Sockets;

namespace Letter.Net.Session;

static class SocketOperationUtil
{
    public static bool TryNormalCompletion(SocketOperationResult result, out Exception error)
    {
        if (!result.HasError)
        {
            error = null;
            return true;
        }
        
        if (IsConnectionResetError(result.SocketError.SocketErrorCode))
        {
            var ex = result.SocketError;
            error = new ConnectionResetException(ex.Message, ex);
            return false;
        }

        if (IsConnectionAbortError(result.SocketError.SocketErrorCode))
        {
            error = result.SocketError;
            return false;
        }


        error = result.SocketError;

        return false;
    }
    
    public static bool IsConnectionResetError(SocketError errorCode)
    {
        return errorCode == SocketError.ConnectionReset ||
               errorCode == SocketError.Shutdown ||
               (errorCode == SocketError.ConnectionAborted && OS.IsWindows());
    }

    public static bool IsConnectionAbortError(SocketError errorCode)
    {
        // Calling Dispose after ReceiveAsync can cause an "InvalidArgument" error on *nix.
        return errorCode == SocketError.OperationAborted ||
               errorCode == SocketError.Interrupted ||
               (errorCode == SocketError.InvalidArgument && !OS.IsWindows());
    }
}